/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.pig4cloud.pigx.user.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.customize.enums.AbnormalEnum;
import com.pig4cloud.pigx.common.customize.exception.DuckweedException;
import com.pig4cloud.pigx.common.customize.mysql.dto.ExportExcelDTO;
import com.pig4cloud.pigx.common.customize.mysql.utils.ExportExcelUtils;
import com.pig4cloud.pigx.common.customize.mysql.utils.MysqlUtil;
import com.pig4cloud.pigx.common.customize.security.utils.SecurityUtil;
import com.pig4cloud.pigx.common.customize.utils.id.IdWorker;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import com.pig4cloud.pigx.user.constant.RedisKeyPrefixConstant;
import com.pig4cloud.pigx.user.constant.RedisMessageType;
import com.pig4cloud.pigx.user.constant.WalletConstant;
import com.pig4cloud.pigx.user.dto.AppWithdrawalRecordPageDTO;
import com.pig4cloud.pigx.user.dto.ApplyWithdrawalDTO;
import com.pig4cloud.pigx.user.dto.WithdrawalRecordPageDTO;
import com.pig4cloud.pigx.user.dto.WithdrawalToExamineDTO;
import com.pig4cloud.pigx.user.entity.*;
import com.pig4cloud.pigx.user.enums.RechargeRecordEnum;
import com.pig4cloud.pigx.user.enums.TransferEnums;
import com.pig4cloud.pigx.user.enums.WalletStatusEnums;
import com.pig4cloud.pigx.user.mapper.TransferDetailedMapper;
import com.pig4cloud.pigx.user.mapper.WithdrawalRecordMapper;
import com.pig4cloud.pigx.user.service.*;
import com.pig4cloud.pigx.user.vo.AdminPageDemoVO;
import com.pig4cloud.pigx.user.vo.LoginUserWithdrawalRecordVO;
import com.pig4cloud.pigx.user.vo.UserWithdrawalInfoVO;
import lombok.AllArgsConstructor;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 提现记录
 *
 * @author pigx code generator
 * @date 2022-11-28 16:16:25
 */
@Service
@AllArgsConstructor
public class WithdrawalRecordServiceImpl extends ServiceImpl<WithdrawalRecordMapper, WithdrawalRecord> implements WithdrawalRecordService {

	private final StringRedisTemplate stringRedisTemplate;

	private final UserService userService;

	private final CapitalAccountService capitalAccountService;

	private final UserAddressService accountService;

	private final MysqlUtil mysqlUtil;

	private final CurrencyService currencyService;

	private final RedisTemplate redis;

	private final TransferDetailedMapper transferMapper;

	private final IdWorker idWorker;

	private final ExportExcelUtils excelUtils;


	@Override
	public R<Page<LoginUserWithdrawalRecordVO>> getAppPage(AppWithdrawalRecordPageDTO dto) {
		try {
			PigxUser user = SecurityUtil.getLoginUser();
			if (user == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
			Page<WithdrawalRecord> page = baseMapper.selectPage(new Page<WithdrawalRecord>() {{
				setCurrent(dto.getCurrent());
				setSize(dto.getSize());
			}}, new QueryWrapper<WithdrawalRecord>() {{
				eq("user_id", user.getId());
				if (dto.getStartTime() != null) {
					ge("create_time", dto.getStartTime());
				}
				if (dto.getEndTime() != null) {
					le("create_time", dto.getEndTime());
				}
				if (dto.getType() != null && !dto.getType().isEmpty()) {
					eq("type", dto.getType());
				}
				orderByDesc("create_time");
			}});
			Page<LoginUserWithdrawalRecordVO> voPage = new Page<>();
			BeanUtils.copyProperties(page,voPage);
			List<LoginUserWithdrawalRecordVO> voList = new ArrayList<>();
			for (WithdrawalRecord record : page.getRecords()) {
				LoginUserWithdrawalRecordVO vo = new LoginUserWithdrawalRecordVO();
				BeanUtils.copyProperties(record,vo);
				vo.setState(WalletStatusEnums.Status.findName(vo.getState()));
				vo.setType("0".equals(record.getType()) ? "充值提现" : "奖励提现");
				if (vo.getQuantity() != null) {
					vo.setQuantity(vo.getQuantity().setScale(6, RoundingMode.DOWN).stripTrailingZeros());
				}
				if (vo.getServiceCharge() != null) {
					vo.setServiceCharge(vo.getServiceCharge().setScale(6, RoundingMode.DOWN).stripTrailingZeros());
				}
				if (vo.getActualWithdrawalAmount() != null) {
					vo.setActualWithdrawalAmount(vo.getActualWithdrawalAmount().setScale(6, RoundingMode.DOWN).stripTrailingZeros());
				}
				voList.add(vo);
			}
			voPage.setRecords(voList);
			return R.ok(voPage);
		} catch (DuckweedException ignored) {
			throw ignored;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 申请提现
	 * @return r
	 */
	@Override
	public R<String> create(ApplyWithdrawalDTO dto) {
		try {
			// 必填校验
			if (dto.getArrivalAddress() == null || dto.getArrivalAddress().isEmpty()) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"到账地址不能为空");
			}
			if (dto.getChain() == null || dto.getChain().isEmpty()) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"公链不能为空");
			}
			if (dto.getType() == null || dto.getType().isEmpty()) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"提现类型不能为空");
			}
			if (dto.getQuantity() == null || dto.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"提现数量不可小于等于0");
			}
			if (dto.getCurrency() == null || dto.getCurrency().isEmpty()) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"币种不能为空");
			}
			// 获取币种
			Currency currency = currencyService.getCurrency(WalletConstant.USDT,dto.getChain());
			if (dto.getQuantity().compareTo(currency.getMinimumWithdrawalAmount()) < 0) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"提现数量不可少于最小提现金额");
			}
			PigxUser pigxUser = SecurityUtils.getUser();
			// 检测是否有未完成的提现申请
			Long count = baseMapper.selectCount(new QueryWrapper<WithdrawalRecord>() {{
				eq("user_id", pigxUser.getId());
				in("state", WalletStatusEnums.Status.UNDER_REVIEW.getValue(), WalletStatusEnums.Status.WITHDRAWING.getValue());
			}});
			if (count > 0) {
				throw new DuckweedException(AbnormalEnum.MSG.UNSUPPORTED_OPERATION.getCode(),"您还有一笔未处理完成的提现申请,请勿重复提交申请");
			}
			// 邮箱验证码
			String key = pigxUser.getEmail() + " massage = " + RedisMessageType.Withdrawal_Request;
			String codeRedis = stringRedisTemplate.opsForValue().get(key);
			if (!StrUtil.equals(dto.getVerificationCode(), codeRedis)) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"验证码错误");
			}
			// 校验资金密码
			User user = userService.getById(pigxUser.getId());
			if (user == null || !dto.getPassword().equals(user.getPassword())) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"资金密码错误");
			}
			// 查询用户地址
			UserAddress account = accountService.getOne(new LambdaQueryWrapper<UserAddress>()
					.eq(UserAddress::getUserId, pigxUser.getId())
					.eq(UserAddress::getChain, dto.getChain())
			);
			if (account == null) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"未找到该用户地址");
			}
			mysqlUtil.startLocalTx();
			// 校验资金账户余额
			CapitalAccount capitalAccount = capitalAccountService.getOne(new QueryWrapper<CapitalAccount>(){{
				eq("user_id",user.getId());
				eq("currency",WalletConstant.USDT);
				last("for update");
			}});
			int compare = -1;
			// type = 0 为充值提现 1为奖励提现
			if ("0".equals(dto.getType())) {
				compare = capitalAccount.getBalance().compareTo(dto.getQuantity());
			} else if ("1".equals(dto.getType())) {
				compare = capitalAccount.getFrozen().compareTo(dto.getQuantity());
			}
			if (compare < 0) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"可提余额不足");
			}
			// 校验贡献值是否足够
			int compareTo = capitalAccount.getContributionValue().compareTo(dto.getQuantity());
			if (compareTo < 0) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"贡献值不足,无法提现");
			}
			// 预扣除资金和贡献值
			if ("0".equals(dto.getType())) {
				capitalAccount.setBalance(capitalAccount.getBalance().subtract(dto.getQuantity()));
			} else if ("1".equals(dto.getType())) {
				capitalAccount.setFrozen(capitalAccount.getFrozen().subtract(dto.getQuantity()));
			}
			capitalAccount.setContributionValue(capitalAccount.getContributionValue().subtract(dto.getQuantity()));
			capitalAccountService.updateById(capitalAccount);
			// 记录提现申请
			WithdrawalRecord withdrawalRecordSave = new WithdrawalRecord();
			withdrawalRecordSave.setId(IdUtil.getSnowflakeNextId());
			withdrawalRecordSave.setQuantity(dto.getQuantity());
			withdrawalRecordSave.setState(WalletStatusEnums.Status.UNDER_REVIEW.getValue());
			withdrawalRecordSave.setAccountId(account.getId());
			withdrawalRecordSave.setUserId(pigxUser.getId());
			withdrawalRecordSave.setCurrency(WalletConstant.USDT);
			withdrawalRecordSave.setPublicChain(dto.getChain());
			withdrawalRecordSave.setArrivalAddress(dto.getArrivalAddress());
			withdrawalRecordSave.setServiceCharge(currency.getServiceCharge().multiply(dto.getQuantity()));
			withdrawalRecordSave.setType(dto.getType());
			baseMapper.insert(withdrawalRecordSave);
			mysqlUtil.commitLocalTx();
			stringRedisTemplate.delete(key);
			return R.ok("提现申请成功!");
		} catch (DuckweedException ignored) {
			mysqlUtil.rollbackLocalTx();
			throw ignored;
		} catch (Exception e) {
			mysqlUtil.rollbackLocalTx();
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	@Override
	public R<UserWithdrawalInfoVO> getUserInfo(Long userId) {
		UserWithdrawalInfoVO vo = new UserWithdrawalInfoVO();
		// 累计充值/累计奖励
		// 查询累计充值和累计奖励
		RechargeRecord rechargeRecord = new RechargeRecord().selectOne(new QueryWrapper<RechargeRecord>() {{
			eq("user_id", userId);
			eq("type", RechargeRecordEnum.Type.USER_RECHARGE.getValue());
			eq("state", RechargeRecordEnum.Status.SUCCESS.getValue());
			select("sum(quantity) 'quantity'");
		}});
		vo.setRecharge(rechargeRecord != null && rechargeRecord.getQuantity() != null  ? rechargeRecord.getQuantity() : BigDecimal.ZERO);
		RechargeRecord chainRecord = new RechargeRecord().selectOne(new QueryWrapper<RechargeRecord>() {{
			eq("user_id", userId);
			eq("type", RechargeRecordEnum.Type.CHAIN_RECHARGE.getValue());
			eq("state", RechargeRecordEnum.Status.SUCCESS.getValue());
			select("sum(quantity) 'quantity'");
		}});
		vo.setChainRecharge(chainRecord != null && chainRecord.getQuantity() != null  ? chainRecord.getQuantity() : BigDecimal.ZERO);
		RechargeRecord record = new RechargeRecord().selectOne(new QueryWrapper<RechargeRecord>() {{
			eq("user_id", userId);
			notIn("type", RechargeRecordEnum.Type.CHAIN_RECHARGE.getValue(),RechargeRecordEnum.Type.USER_RECHARGE.getValue());
			eq("state", RechargeRecordEnum.Status.SUCCESS.getValue());
			select("sum(quantity) 'quantity'");
		}});
		vo.setReward(record != null && record.getQuantity() != null ? record.getQuantity() : BigDecimal.ZERO);
		// 累计购买燃料包
		TransferDetailed detailed = new TransferDetailed().selectOne(new QueryWrapper<TransferDetailed>() {{
			eq("user_id", userId);
			eq("type", TransferEnums.Type.TO_FUEL.getValue());
			select("sum(quantity) quantity");
		}});
		vo.setFuel(detailed != null && detailed.getQuantity() != null ? detailed.getQuantity() : BigDecimal.ZERO);
		return R.ok(vo);
	}

	@Override
	public R<String> transfer(BigDecimal num) {
		try {
			if (num == null) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"数量不能为空");
			}
			if (num.compareTo(BigDecimal.ZERO) <= 0) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"数量不能为0");
			}
			mysqlUtil.startLocalTx();
			PigxUser pigxUser = SecurityUtils.getUser();
			CapitalAccount capitalAccount = capitalAccountService.getOne(new QueryWrapper<CapitalAccount>(){{
				eq("user_id",pigxUser.getId());
				eq("currency",WalletConstant.USDT);
				last("for update");
			}});
			if (capitalAccount.getFrozen().compareTo(num) < 0) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"奖励账户余额不足");
			}
			capitalAccount.setFrozen(capitalAccount.getFrozen().subtract(num));
			capitalAccount.setBalance(capitalAccount.getBalance().add(num));
			capitalAccount.updateById();
			transferMapper.insert(new TransferDetailed(){{
				setId(idWorker.nextId());
				setUserId(pigxUser.getId());
				setQuantity(num);
				setCurrency(WalletConstant.USDT);
				setType(TransferEnums.Type.REWARD.getValue());
			}});
			mysqlUtil.commitLocalTx();
			return R.ok("划转成功");
		} catch (Exception e) {
			mysqlUtil.rollbackLocalTx();
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}


	/**
	 * 提现审核
	 * @param dto dto
	 * @return r
	 */
	@Override
	public R<String> toExamine(WithdrawalToExamineDTO dto) {
		// 审核拒绝 => 直接退回资金
		if (dto.getState().equals(WalletStatusEnums.Status.REJECTED.getValue())) {
			return refuse(dto.getId(),dto.getRemarks());
		}
		// 审核通过
		if (dto.getState().equals(WalletStatusEnums.Status.WITHDRAWING.getValue())) {
			return adopt(dto);
		}
		throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN_ORDER_COMPOSITION.getCode(),"审核类型错误");
	}

	/**
	 * 审核通过
	 * @param dto
	 * @return
	 */
	private R<String> adopt(WithdrawalToExamineDTO dto) {
		try {
			if (dto.getSourceAddress() == null || dto.getSourceAddress().isEmpty()) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"来源地址不可为空");
			}
			if (dto.getTransactionHash() == null || dto.getTransactionHash().isEmpty()) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"交易哈希不可为空");
			}
			if (dto.getActualWithdrawalAmount() == null) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"实际提现数量不可为空");
			}
			WithdrawalRecord record = baseMapper.selectById(dto.getId());
			if (record == null) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"查询不到该提现记录");
			}
			baseMapper.updateById(new WithdrawalRecord(){{
				setId(record.getId());
				setState(dto.getState());
				setSourceAddress(dto.getSourceAddress());
				setTransactionHash(dto.getTransactionHash());
				setActualWithdrawalAmount(dto.getActualWithdrawalAmount());
				setRemarks(dto.getRemarks());
			}});
			redis.opsForHash().put(RedisKeyPrefixConstant.WITHDRAWAL_RECORD_CHECK,record.getId().toString(),0);
			return R.ok("提现进行中");
		} catch (DuckweedException ignored) {
			mysqlUtil.rollbackLocalTx();
			throw ignored;
		} catch (Exception e) {
			mysqlUtil.rollbackLocalTx();
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 审核拒绝
	 * @param id 提现记录id
	 * @param remarks 备注
	 */
	private R<String> refuse(Long id,String remarks) {
		try {
			WithdrawalRecord record = baseMapper.selectById(id);
			if (record == null) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"查询不到该提现记录");
			}
			mysqlUtil.startLocalTx();
			// 返还预扣除资金和贡献值
			CapitalAccount capitalAccount = capitalAccountService.getOne(new QueryWrapper<CapitalAccount>(){{
				eq("user_id",record.getUserId());
				eq("currency",WalletConstant.USDT);
				last("for update");
			}});
			if ("0".equals(record.getType())) {
				capitalAccount.setBalance(capitalAccount.getBalance().add(record.getQuantity()));
			} else if ("1".equals(record.getType())) {
				capitalAccount.setFrozen(capitalAccount.getFrozen().add(record.getQuantity()));
			}
			capitalAccount.setContributionValue(capitalAccount.getContributionValue().add(record.getQuantity()));
			capitalAccountService.updateById(capitalAccount);
			// 修改提现申请状态为已拒绝
			record.setState(WalletStatusEnums.Status.REJECTED.getValue());
			record.setRemarks(remarks);
			baseMapper.updateById(record);
			mysqlUtil.commitLocalTx();
			return R.ok("提现拒绝成功");
		} catch (DuckweedException ignored) {
			mysqlUtil.rollbackLocalTx();
			throw ignored;
		} catch (Exception e) {
			mysqlUtil.rollbackLocalTx();
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	@Override
	public R<AdminPageDemoVO<WithdrawalRecord>> getWithdrawalRecordPage(WithdrawalRecordPageDTO dto) {
		QueryWrapper<WithdrawalRecord> wrapper = new QueryWrapper<WithdrawalRecord>() {{
			if (dto.getUserId() != null) {
				like("user_id", dto.getUserId());
			}
			if (dto.getHash() != null && !dto.getHash().isEmpty()) {
				like("transaction_hash", dto.getHash());
			}
			if (dto.getType() != null && !dto.getType().isEmpty()) {
				eq("type", dto.getType());
			}
			if (dto.getChain() != null && !dto.getChain().isEmpty()) {
				eq("public_chain",dto.getChain());
			}
			if (dto.getStartTime() != null) {
				ge("create_time", dto.getStartTime());
			}
			if (dto.getEndTime() != null) {
				le("create_time", dto.getEndTime());
			}
			orderByDesc("create_time");
		}};
		// 分页数据
		Page<WithdrawalRecord> page = baseMapper.selectPage(new Page<WithdrawalRecord>() {{
			setCurrent(dto.getCurrent());
			setSize(dto.getSize());
		}}, wrapper);
		for (WithdrawalRecord record : page.getRecords()) {
			record.setState(WalletStatusEnums.Status.findName(record.getState()));
			record.setType("0".equals(record.getType()) ? "充值提现" : "奖励提现");
			if (record.getQuantity() != null) {
				record.setQuantity(record.getQuantity().setScale(6, RoundingMode.DOWN).stripTrailingZeros());
			}
			if (record.getServiceCharge() != null) {
				record.setServiceCharge(record.getServiceCharge().setScale(6, RoundingMode.DOWN).stripTrailingZeros());
			}
			if (record.getActualWithdrawalAmount() != null) {
				record.setActualWithdrawalAmount(record.getActualWithdrawalAmount().setScale(6, RoundingMode.DOWN).stripTrailingZeros());
			}
		}
		// 统计数据
		WithdrawalRecord one = baseMapper.selectOne(wrapper
				.select("sum(quantity) 'quantity'," +
						"sum(service_charge) 'serviceCharge'," +
						"sum(actual_withdrawal_amount) 'actualWithdrawalAmount'")
				.eq("state",WalletStatusEnums.Status.SUCCESS.getValue())
		);
		return R.ok(new AdminPageDemoVO<WithdrawalRecord>(){{
			setPage(page);
			setStatistics(one);
		}});
	}

	public HSSFWorkbook excel(WithdrawalRecordPageDTO dto) {
		// 初始化excel参数
		ExportExcelDTO excelDTO = new ExportExcelDTO();
		// 自定义表头长度
		List<Short> columnWidth = new ArrayList<Short>(){{
			add((short) 180);
			add((short) 200);
			add((short) 200);
			add((short) 300);
			add((short) 100);
			add((short) 120);
			add((short) 120);
			add((short) 120);
			add((short) 100);
			add((short) 100);
			add((short) 300);
			add((short) 200);
		}};
		excelDTO.setColumnWidth(columnWidth);
		// 自定义表头名称
		List<String> columnLabel = new ArrayList<String>(){{
			add("用户ID");
			add("来源地址");
			add("到账地址");
			add("交易哈希");
			add("公链");
			add("数量");
			add("手续费");
			add("实际提现金额");
			add("状态");
			add("类型");
			add("审核备注");
			add("提现时间");
		}};
		excelDTO.setColumnLabel(columnLabel);
		excelDTO.setHeaderTitle("提现记录统计报表");
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		excelDTO.setHeaderTime(
				(dto.getStartTime() != null ? df.format(dto.getStartTime()) : " ∞ ")
				+ " => " +
				(dto.getEndTime() != null ? df.format(dto.getEndTime()) : " ∞ ")
		);
		HSSFWorkbook wb = new HSSFWorkbook();
		// 默认sheet1
		HSSFSheet sheet = wb.createSheet("sheet1");
		// 统一格式初始化
		excelUtils.init(excelDTO,wb,sheet);
		// 单元格
		HSSFCell cell;
		// 初始化数据单元格的样式
		HSSFCellStyle labelStyle = ExportExcelUtils.getCellStyle(wb, null, (short) 11,false);
		// 基础数据起始行
		int startRow = 3;
		// 查询需要导出的数据
		dto.setCurrent(1L);
		dto.setSize(100000L);
		// 根据检索获取数据
		R<AdminPageDemoVO<WithdrawalRecord>> recordPage = getWithdrawalRecordPage(dto);
		List<WithdrawalRecord> list = recordPage.getData().getPage().getRecords();
		WithdrawalRecord record = recordPage.getData().getStatistics();
		// 循环写入数据
		for (int i = 0; i < list.size(); i++) {
			// 行数
			int createRow = startRow + i;
			// 创建行
			HSSFRow label = sheet.createRow(createRow);
			// 用户ID
			cell = label.createCell(0);
			cell.setCellValue(list.get(i).getUserId().toString());
			cell.setCellStyle(labelStyle);
			// 来源地址
			cell = label.createCell(1);
			cell.setCellValue(list.get(i).getSourceAddress());
			cell.setCellStyle(labelStyle);
			// 到账地址
			cell = label.createCell(2);
			cell.setCellValue(list.get(i).getArrivalAddress());
			cell.setCellStyle(labelStyle);
			// 交易哈希
			cell = label.createCell(3);
			cell.setCellValue(list.get(i).getTransactionHash());
			cell.setCellStyle(labelStyle);
			// 公链
			cell = label.createCell(4);
			cell.setCellValue(list.get(i).getPublicChain());
			cell.setCellStyle(labelStyle);
			// 数量
			cell = label.createCell(5);
			cell.setCellValue(list.get(i).getQuantity().setScale(6,RoundingMode.DOWN).stripTrailingZeros().toPlainString());
			cell.setCellStyle(labelStyle);
			// 手续费
			cell = label.createCell(6);
			cell.setCellValue(list.get(i).getServiceCharge().setScale(6,RoundingMode.DOWN).stripTrailingZeros().toPlainString());
			cell.setCellStyle(labelStyle);
			// 实际提现金额
			cell = label.createCell(7);
			if (list.get(i).getActualWithdrawalAmount() != null) {
				cell.setCellValue(list.get(i).getActualWithdrawalAmount().setScale(6,RoundingMode.DOWN).stripTrailingZeros().toPlainString());
			} else {
				cell.setCellValue("");
			}
			cell.setCellStyle(labelStyle);
			// 状态
			cell = label.createCell(8);
			cell.setCellValue(list.get(i).getState());
			cell.setCellStyle(labelStyle);
			// 类型
			cell = label.createCell(9);
			cell.setCellValue(list.get(i).getType());
			cell.setCellStyle(labelStyle);
			// 审核备注
			cell = label.createCell(10);
			cell.setCellValue(list.get(i).getRemarks());
			cell.setCellStyle(labelStyle);
			// 提现时间
			cell = label.createCell(11);
			cell.setCellValue(df.format(list.get(i).getCreateTime()));
			cell.setCellStyle(labelStyle);
		}
		// 最后一行做统计
		if (record != null) {
			HSSFCellStyle totalStyle = ExportExcelUtils.getCellStyle(wb, IndexedColors.PALE_BLUE.index, (short) 11,false);
			int totalRow = startRow + list.size();
			HSSFRow label = sheet.createRow(totalRow);

			cell = label.createCell(0);
			cell.setCellValue("统计数据");
			cell.setCellStyle(totalStyle);

			cell = label.createCell(1);
			cell.setCellValue("/");
			cell.setCellStyle(totalStyle);

			cell = label.createCell(2);
			cell.setCellValue("/");
			cell.setCellStyle(totalStyle);

			cell = label.createCell(3);
			cell.setCellValue("/");
			cell.setCellStyle(totalStyle);

			cell = label.createCell(4);
			cell.setCellValue("/");
			cell.setCellStyle(totalStyle);

			cell = label.createCell(5);
			cell.setCellValue(record.getQuantity().setScale(6,RoundingMode.DOWN).stripTrailingZeros().toPlainString());
			cell.setCellStyle(totalStyle);

			cell = label.createCell(6);
			cell.setCellValue(record.getServiceCharge().setScale(6,RoundingMode.DOWN).stripTrailingZeros().toPlainString());
			cell.setCellStyle(totalStyle);

			cell = label.createCell(7);
			if (record.getActualWithdrawalAmount() != null) {
				cell.setCellValue(record.getActualWithdrawalAmount().setScale(6,RoundingMode.DOWN).stripTrailingZeros().toPlainString());
			} else {
				cell.setCellValue("");
			}
			cell.setCellStyle(totalStyle);

			cell = label.createCell(8);
			cell.setCellValue("/");
			cell.setCellStyle(totalStyle);

			cell = label.createCell(9);
			cell.setCellValue("/");
			cell.setCellStyle(totalStyle);

			cell = label.createCell(10);
			cell.setCellValue("/");
			cell.setCellStyle(totalStyle);

			cell = label.createCell(11);
			cell.setCellValue("/");
			cell.setCellStyle(totalStyle);
		}

		return wb;
	}

}
